import { useEffect, useState, useCallback, useRef } from 'react';
import { Form } from 'antd';
import { request } from '@inbiz/utils';
import classnames from 'classnames';
import { cloneDeep } from 'lodash';
import { Editor } from '@tinymce/tinymce-react';
import { GlobalRegistry } from '@inbiz/core';
import { langToIntlKeyforTextArea, getApp, postMessage, MessageType } from '@inbiz/utils';
import { observer } from '@formily/react';
import { getMessage } from '@inbiz/react';
import InsertVideo from './component/InsertVideo';
import {
  muneItemDefault,
  allMune,
  allTool,
} from './static';

import './style.less';

// 应用版本号
const version = InbizConfig.API_VERSION;

interface TinymceProps {
  /**
   * 组件样式前缀
   */
  prefixCls?: string;
  // 富文本初始化内容
  initialValue?: string;
  /**
   * 富文本主体内容
   */
  EditorValue?: any;
  /**
   * 空值提示文字
   */
  placeholder?: string;
  /**
   * 富文本数据改变方法
   */
  onChange?: any;
  /**
   * 编辑器风格(功能)
   */
  tooltype?: '标准' | '简洁' | '极简' | '自定义';
  /**
   * 菜单及工具栏配置数据
   */
  tinymceConfig?: {
    menu: string[];
    toolbar: string[];
  };
  /**
   * 容器高度
   */
  boxHeight?: any;
  /**
   * 是否只读
   */
  readOnly?: any;
  /**
   * 图片上传地址
   */
  imguploadurl?: string;
  /**
   * 视频上传地址
   */
  videouploadurl?: string;
  contentStyle?: string;
}

export default observer((props: TinymceProps) => {
  const {
    prefixCls = 'inbiz-Tinymce',
    onChange,
    EditorValue,
    initialValue,
    placeholder,
    tooltype,
    boxHeight = 300,
    tinymceConfig = {
      menu: [],
      toolbar: [],
    },
    readOnly,
    imguploadurl,
    videouploadurl,
    contentStyle,
  } = props;
  // 站点信息
  const appInfo = getApp();
  // 富文本控制重渲染的key
  const [refresh, $refresh] = useState(0);
  // 富文本是否获取焦点
  const [editorFocus, $editorFocus] = useState<boolean>(false);
  // 菜单配置
  const [muneConfig, $muneConfig] = useState<string>('');
  // 菜单单项配置
  const [muneItemConfig, $muneItemConfig] = useState<any>(muneItemDefault);
  // 工具栏配置
  const [toolConfig, $toolConfig] = useState<string>('');
  // 菜单及工具栏配置数据(字符串)
  const tinyConfigString = useRef(JSON.stringify({ menu: [], toolbar: [] }));
  // 插入/编辑视频弹窗显示
  const [videoVisible, $videoVisible] = useState(false)
  // 插入/编辑视频弹窗表单
  const [form] = Form.useForm()
  // 是否全屏了
  const isFull = useRef(false);
  // 富文本设计器对象
  const editorRef = useRef<any>();

  // 富文本自定义配置变化发起配置数据计算
  useEffect(() => {
    if (JSON.stringify(tinymceConfig) !== tinyConfigString.current) {
      tinyConfigString.current = JSON.stringify(tinymceConfig);
      const { menu, toolbar } = tinymceConfig || {};
      menu && menuMake(menu);
      toolbar && toolMake(toolbar);
    }
  }, [tinymceConfig]);

  // 多语言切换、菜单、工具栏、提示文字、容器高度、类型 数据变化刷新富文本
  useEffect(() => {
    $refresh((pre: number) => pre + 1);
  }, [
    GlobalRegistry.getDesignerLanguage(),
    muneConfig,
    muneItemConfig,
    toolConfig,
    placeholder,
    boxHeight,
    tooltype,
  ]);

  // 菜单栏数据处理
  const menuMake = useCallback((list: string[]) => {
    // 选中应显示的菜单
    const menuList: string[] = [];
    // 选中的菜单配置
    const menuItem = {
      file: {
        title: 'File',
        items: ['newdocument', 'preview', 'print'],
      },
      edit: {
        title: 'Edit',
        items: [
          'undo',
          'redo',
          'cut',
          'copy',
          'paste',
          'pastetext',
          'selectall',
          'searchreplace',
        ],
      },
      view: {
        title: 'View',
        items: [
          'code-view',
          'visualaid',
          'visualchars',
          'visualblocks',
          'preview-view',
          'fullscreen',
        ],
      },
      insert: {
        title: 'Insert',
        items: [
          'image',
          'link',
          'media',
          'inserttable',
          'charmap',
          'hr',
          'pagebreak',
          'nonbreaking',
          'anchor',
          'insertdatetime',
        ],
      },
      format: {
        title: 'Format',
        items: [
          'bold',
          'italic',
          'underline',
          'strikethrough',
          'superscript',
          'subscript',
          'codeformat',
          'forecolor',
          'backcolor',
          'removeformat',
          'styles',
          'blocks',
          'fontfamily',
          'fontsize',
          'align',
          'lineheight',
        ],
      },
      table: {
        title: 'Table',
        items: [
          'inserttable-view',
          'cell',
          'row',
          'column',
          'tableprops',
          'deletetable',
        ],
      },
      tools: {
        title: 'Tools',
        items: ['code', 'wordcount'],
      },
    };
    // 全选子项的菜单
    let pickMune = list.filter((item: string) => allMune.includes(item));
    /*** 找到被全选了的菜单项 ***/
    allMune.forEach((item: string) => {
      if (pickMune.includes(item)) {
        menuList.push(item);
      }
    });
    /***  找到没被全选的菜单项 ***/
    allMune.forEach((item: string) => {
      if (!menuList.includes(item)) {
        // @ts-ignore
        const menuItemVal = menuItem[item.toLocaleLowerCase()];
        const picks: string[] = [];
        list.forEach((val: string) => {
          if (menuItemVal.items.includes(val)) {
            if (!menuList.includes(item)) {
              // 父级菜单未被选中时选中父级菜单
              menuList.push(item);
            }
            picks.push(val);
          }
        });
        /*** 排序非全选子项的菜单子项 ***/
        menuItemVal.items = menuItemVal.items.filter((val: string) =>
          picks.includes(val),
        );
      }
    });
    /*** 数据排序转小写后拼接成字符串 ***/
    let afterMenu = allMune
      .filter((item: string) => menuList.includes(item))
      .map((item: string) => item.toLocaleLowerCase())
      .join(' ');
    allMune.forEach((ele: string) => {
      // @ts-ignore
      const record = menuItem[ele.toLocaleLowerCase()];
      /* 自定义上传视频替换默认多媒体 media => customUploadVideoMenu */
      record.items = record.items.join(' ').replaceAll('-view', '').replaceAll('media', 'customUploadVideoMenu');
    });
    $muneConfig(afterMenu);
    $muneItemConfig(menuItem);
  }, []);

  // 工具栏数据处理
  const toolMake = useCallback((list: string[]) => {
    const arr: string[] = [];
    const checks = cloneDeep(list);
    allTool.forEach((item: string) => {
      if (checks.includes(item)) {
        arr.push(item);
      }
    });
    /* 自定义上传视频替换默认多媒体 media => customUploadVideoMenu */
    // @ts-ignore
    const checkString: string = arr.join(' ').replaceAll('media', 'customUploadVideo');
    $toolConfig(checkString);
  }, []);

  // 图片上传方法
  const uploadImage = useCallback(
    (params: any) => {
      const data = new FormData();
      for (let k in params) {
        if (params[k] && params[k] instanceof File) {
          data.append(k, params[k], params[k].type);
        } else {
          data.append(k, params[k]);
        }
      }
      // @ts-ignore
      return request(imguploadurl, {
        method: 'POST',
        params: {
          // @ts-ignore
          siteOutId: appInfo?.SiteInfo?.OutId,
          appId: appInfo?.AppId,
          version,
        },
        data: data,
        //@ts-ignore
        requestType: 'formData',
        intercept: true,
        timeout: 0,
        headers: {
          // @ts-ignore
          appId: appInfo?.AppId
        }
      }).then((res: any) => {
        if (res?.Success) {
          if (res.FilePath.substr(0, 5) != 'http:') {
            if (res.FilePath.substr(0, 1) != '/') {
              res.FilePath = '/' + res.FilePath;
            }
          }
          // message通讯
          let messageData: MessageType = {
            module: 'staticResource',
            event: 'add',
            data: {
              filePath: res.FilePath
            },
          };
          postMessage(messageData);
          if (res.FilePath.indexOf('{AppId}') > -1) {
            res.FilePath = res.FilePath.replace('{AppId}', appInfo?.AppId);
          }
        }
        return res;
      });
    },
    [imguploadurl, appInfo, version],
  );

  return (
    <div
      className={classnames(`${prefixCls}-TinymceBox`, {
        'inbiz-Tinymce-TinymceBox-disable': readOnly,
        'inbiz-Tinymce-TinymceBox-focus': editorFocus === true,
      })}
    >
      <Editor
        key={refresh}
        tinymceScriptSrc={`${InbizConfig.PUBLIC_PATH}/js/tinymce/tinymce.min.js?v=6.7.0`}
        init={{
          promotion: false,
          height: boxHeight, // 容器高度
          menubar:
            tooltype == '标准'
              ? true
              : tooltype != '自定义'
                ? false
                : muneConfig?.length
                  ? muneConfig
                  : false, // 模式(标准 | 简洁 | 极简 | 自定义)(文件file | 编辑edit | 视图view | 插入insert | 格式format | 表格table | 工具tools)
          menu: tooltype != '自定义' ? muneItemDefault : muneItemConfig,
          language: langToIntlKeyforTextArea(
            GlobalRegistry.getDesignerLanguage(),
          ), // 语言: zh_CN中文, en_US英语, ja日文
          plugins:
            'advlist autolink lists link image charmap preview anchor searchreplace visualblocks visualchars code fullscreen insertdatetime customUploadVideo table code wordcount pagebreak nonbreaking ', // 插件
          /* 备份原始配置-自定义上传视频替换默认多媒体 media => customUploadVideoMenu */
          // 'customUploadVideo advlist autolink lists link image charmap preview anchor searchreplace visualblocks visualchars code fullscreen insertdatetime media table code wordcount pagebreak nonbreaking ',
          font_size_formats: '8px 10px 12px 14px 16px 18px 24px 36px', // 可选字体大小
          placeholder: `${placeholder ? placeholder : ''}`, // 空值提示
          convert_urls: false, // 自动处理url(不允许，处理url对丢失路径，绝对地址会变成相对地址)
          content_style: `body { font-family:Helvetica,Arial,sans-serif; font-size:14px }; ${contentStyle || ''
            }`, // 容器样式
          toolbar:
            tooltype == '自定义'
              ? toolConfig
              : tooltype == '极简'
                ? 'styles bold italic bullist numlist link image'
                : `${tooltype == '标准' ? 'undo redo' : ''} |` +
                'bold italic forecolor backcolor | ' +
                `${tooltype == '标准'
                  ? 'bullist numlist alignleft aligncenter alignright alignjustify outdent indent '
                  : ''
                }|` +
                'fontsize | ' +
                'styles removeformat|' +
                'table link unlink customUploadVideo image preview fullscreen', // 工具栏
          /* 备份原始配置-自定义上传视频替换默认多媒体 media => customUploadVideoMenu */
          // 'table link unlink media image preview fullscreen customUploadVideo', 
          toolbar_mode: 'sliding', // 工具栏单行显示不下的显示方式 sliding | floating | scrolling | wrap 滑动 | 浮动 | 滚动 | 换行
          resize: false, // 控制用户调整编辑器大小
          images_file_types:
            'jpeg,jpg,jpe,jfi,jif,tif,tiff,jfif,png,gif,bmp,webp,svg,pjp,xbm,jxl,svgz,ico,pjpeg,avif', // 支持上传的图片格式
          block_formats:
            'Paragraph=p;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6;Preformatted=p', // 自定义基块配置
          images_upload_handler: (blobInfo) =>
            new Promise((resolve, reject) => {
              // 图片上传处理
              uploadImage({
                fileName: blobInfo.filename(),
                imgSize: 5,
                imgFormat: [
                  'jpg',
                  'png',
                  'bmp',
                  'jpeg',
                  'gif',
                  'svg+xml',
                  'svg',
                ],
                imgHead: blobInfo.blob(),
              })
                .then((res) => {
                  if (res.Success) {
                    resolve(res.FilePath);
                  } else {
                    if (res?.Error?.Message) {
                      reject({ message: res.Error.Message });
                    } else {
                      reject({
                        message: getMessage('Tinymce.message_upload_failed'), // 上传失败
                      });
                    }
                  }
                })
                .catch((e) => {
                  if (e?.Error?.Message) {
                    reject({ message: e.Error.Message });
                  } else {
                    reject({
                      message: getMessage('Tinymce.message_upload_failed'),
                    });
                  }
                });
            }),
          skin: 'oxide', // 样式主题(oxide-dark深色/oxide浅色)
          setup: (editor) => {
            editorRef.current = editor
            editor.on('init', () => {
              editor.getContainer().style.transition =
                'border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out';
            });
            editor.on('FullscreenStateChanged', (e) => {
              isFull.current = e.state;
            });
            editor.on('keyup', (e) => {
              if (e.code == 'KeyF' && e.shiftKey == true && e.ctrlKey == true) {
                editor.execCommand('mceFullScreen');
              } else if (e.code == 'Escape' && isFull.current == true) {
                editor.execCommand('mceFullScreen');
              }
            });
            editor.on('focus', () => {
              $editorFocus(true);
            });
            editor.on('blur', () => {
              $editorFocus(false);
            });
            editor.ui.registry.addIcon(
              'videoIcon',
              `<svg t="1698888192293" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="26" height="26"><path d="M204.8 236.8A19.2 19.2 0 0 0 185.6 256v512c0 10.5984 8.6016 19.2 19.2 19.2h614.4a19.2 19.2 0 0 0 19.2-19.2V256A19.2 19.2 0 0 0 819.2 236.8H204.8z m0-64h614.4c45.9264 0 83.2 37.2736 83.2 83.2v512c0 45.9264-37.2736 83.2-83.2 83.2H204.8A83.2 83.2 0 0 1 121.6 768V256c0-45.9264 37.2736-83.2 83.2-83.2z"></path><path d="M670.7712 485.0176a52.48 52.48 0 0 1-17.9712 71.9872l-195.7376 117.4016a52.48 52.48 0 0 1-79.4624-44.9536V394.5472a52.48 52.48 0 0 1 79.4624-44.9536L652.8 466.944c7.3728 4.4544 13.568 10.5984 17.9712 18.0224z m-229.1712-70.144v194.2016L603.392 512l-161.792-97.0752z"></path></svg>`
            )
            editor.ui.registry.addMenuItem('customUploadVideoMenu', {
              icon: 'videoIcon',
              text: getMessage('Tinymce.video'), // 视频...
              onAction: () => {
                const dom: any = editor.selection.getNode()
                $videoVisible(true)
                if (dom.tagName == 'VIDEO') {
                  const obj = {
                    width: String(dom?.clientWidth),
                    height: String(dom?.clientHeight),
                    src: dom?.dataset?.mceSrc,
                    suo: {
                      pick: true,
                      num: dom?.clientHeight / dom?.clientWidth || 0
                    },
                  }
                  form.setFieldsValue(obj)
                } else {
                  form.resetFields()
                  form.setFieldsValue({
                    suo: {
                      pick: true,
                      num: 0
                    }
                  })
                }
              }
            })
            editor.ui.registry.addToggleButton('customUploadVideo', {
              icon: 'videoIcon',
              tooltip: getMessage('Tinymce.insert_edit_video'), // 插入/编辑视频
              onAction: () => {
                const dom: any = editor.selection.getNode()
                $videoVisible(true)
                if (dom.tagName == 'VIDEO') {
                  const obj = {
                    width: String(dom?.clientWidth),
                    height: String(dom?.clientHeight),
                    src: dom?.dataset?.mceSrc,
                    suo: {
                      pick: true,
                      num: dom?.clientHeight / dom?.clientWidth || 0
                    },
                  }
                  form.setFieldsValue(obj)
                } else {
                  form.resetFields()
                  form.setFieldsValue({
                    suo: {
                      pick: true,
                      num: 0
                    }
                  })
                }
              },
              onSetup: (buttonApi) => {
                const editorEventCallback = (eventApi: any) => {
                  buttonApi.setActive(eventApi.element.nodeName.toLowerCase() === 'video');
                };
                editor.on('NodeChange', editorEventCallback);
                return () => editor.off('NodeChange', editorEventCallback);
              }
            })
          },
          save_onsavecallback: true
        }}
        initialValue={getMessage(initialValue)}
        value={EditorValue}
        onEditorChange={(newValue) => {
          onChange(newValue);
        }}
      />
      {/* 插入/编辑视频弹窗 */}
      <InsertVideo
        form={form}
        appInfo={appInfo}
        videoVisible={videoVisible}
        $videoVisible={$videoVisible}
        videouploadurl={videouploadurl}
        editor={editorRef.current}
      />
    </div>
  );
});
